import 'dart:io';
import 'package:intl/intl.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:tuple/tuple.dart';
import 'package:exif/exif.dart';

import 'exif_map.dart';
import 'package:sprintf/sprintf.dart';
import 'package:path/path.dart' as p;
import 'tools.dart';
import 'utils.dart';

const bypass = "bypass";

const List<Tuple2<String, String>> FileNameStyleMap = [
  Tuple2('1' , "yyyyMMdd.HHmmss"),
  Tuple2('2' , "yyyyMMdd_HHmmss"),
  Tuple2('3' , "yyyyMMdd.HH"),
  Tuple2('4' , "yyyyMMdd_HH"),
  Tuple2('5' , "yyyyMMdd"),
  Tuple2('6' , "yyyyMM"),
  Tuple2('7' , "yyyy"),
];

const List<Tuple2<String, String>> NotExifMap = [
  Tuple2('1' , "忽略不处理"),
  Tuple2('2' , "使用文件日期"),
];

const List<Tuple2<String, String>> SaveModeMap = [
  Tuple2('1' , "替换源文件"),
  Tuple2('2' , "复制到新目录")
];

class MainController extends GetxController {
  RxBool isDarkModeEnabled = false.obs;
  onDarkModeStateChanged(bool v) {
    isDarkModeEnabled(v);
    print(v);
    Get.changeTheme(v? ThemeData.dark().copyWith(
        textTheme: ThemeData.dark().textTheme.apply(fontFamily: "HarmonyOS_Sans" ),
        primaryTextTheme: ThemeData.dark().textTheme.apply(fontFamily: "HarmonyOS_Sans")
    ) :
    ThemeData.light().copyWith(
      textTheme: ThemeData.light().textTheme.apply(fontFamily: "HarmonyOS_Sans" ),
      primaryTextTheme: ThemeData.light().textTheme.apply(fontFamily: "HarmonyOS_Sans")
    ));
    // fontFamily: "HarmonyOS_Sans")
  }

  // 递归打开目录
  // RxBool recursive = false.obs;

  // index, old, new, selected, rename[none,ok,err]
  var fileList = <Tuple5<int, FileSystemEntity, String, bool, int>>[].obs;
  var currentSortColumn = 0.obs;
  var isSortAscending = true.obs;

  onFileListSortOld(int i) {
    currentSortColumn(i);
    if (isSortAscending.isTrue) {
      fileList.sort((e, e1) => e1.item2.path.compareTo(e.item2.path));
    } else {
      fileList.sort((e, e1) => e.item2.path.compareTo(e1.item2.path));
    }
    isSortAscending.toggle();
  }
  onFileListSortNew(int i) {
    currentSortColumn(i);
    if (isSortAscending.isTrue) {
      fileList.sort((e, e1) => e1.item3.compareTo(e.item3));
    } else {
      fileList.sort((e, e1) => e.item3.compareTo(e1.item3));
    }
    isSortAscending.toggle();
  }

  // exif info: 原始key 翻译key 值
  var infoList = <Tuple3<String, String, String>>[].obs;

  // 显示Exif信息
  printExifOf(FileSystemEntity e) async {
    // Map<String, IfdTag> data = await readExifFromBytes(await File(path).readAsBytes());
    Map<String, IfdTag> data = {};
    try {
      data = await readExifFromBytes((e as File).readAsBytesSync());
    } catch (e) {
      print("readExifFromBytes error: $e");
    }

    infoList.add(Tuple3("path", "照片路径", e.path));
    infoList.add(Tuple3("image modified", "状态修改时间", e.statSync().changed.toLocal().toString()));
    infoList.add(Tuple3("image modified", "最后访问时间", e.statSync().accessed.toLocal().toString()));
    infoList.add(Tuple3("image modified", "最后修改时间", e.statSync().modified.toLocal().toString()));
    if (data.isEmpty) {
      print("No EXIF information found\n");
      infoList.add(const Tuple3("error", "错误", "No EXIF information found"));
      return;
    }

    if (data.containsKey('JPEGThumbnail')) {
      print('File has JPEG thumbnail');
      // data.remove('JPEGThumbnail');
    }
    // if (data.containsKey('TIFFThumbnail')) {
    //   print('File has TIFF thumbnail');
    //   data.remove('TIFFThumbnail');
    // }

    for (String key in data.keys) {
      // print("$key: ${data[key]}");
      // ignore: avoid_print
      String _key;
      var v = ExifMap[key];
      if (v == "") {
        _key = key;
      }  else if (v == null) {
        _key = "$key*";
      } else {
        _key = v;
      }

      infoList.add(Tuple3(key, _key, data[key].toString()));
    }
  }
  copyToClipper(BuildContext context) {
    Clipboard.setData(ClipboardData(text: infoList.toString()))
      .then((value) => toast(context, msg: "拷贝成功") )
      .onError((error, stackTrace) => toast(context, msg: "拷贝失败:${error.toString()}", sec: 3, ok: false));
  }

  // 展示的图片
  var thumbFile = "".obs;

  @override
  void onInit() {
    // TODO: implement onInit
    super.onInit();
  }

  // 新文件名样式
  RxString fileNameStyleSelected = FileNameStyleMap.first.item1.obs;

  // 无Exif信息处理
  RxString notExifSelected = NotExifMap.first.item1.obs;

  // 存盘类型
  RxString saveModeSelected = SaveModeMap.first.item1.obs;
  String? saveMode2Dir;
  // setSaveModeSelected(String index) {
  //   saveModeSelected(index);
  // }

  var prefix = "";
  void setPrefix(String s) {
    prefix = s;
    print({"prefix: $prefix" });
  }


  clearAll() {
    fileList.clear();
    infoList.clear();
    thumbFile("");
  }

  // 浏览目录
  walkDir(String? path, bool recursive) async {
    if (path == null) { return; }

    var list = await Directory(path)
        .list(recursive: recursive)
        .where((e) {
         var _path = e.path.toLowerCase();
         if (e.statSync().type == FileSystemEntityType.file &&
             (_path.endsWith("jpg") || _path.endsWith("jpeg"))) {
           return true;
         }
         return false;
    }).toList();

    clearAll();
    int i = 0;
    for (var e in list) {
      fileList.add(Tuple5(i++, e, "", false, 0));
    }
    update(fileList);
  }

  // 浏览多个文件
  walkFiles(List<String?>? list) async {
    if (list == null) { print("list is null"); return; }

    clearAll();
    int i = 0;
    for (var path in list) {
      if (path == null) { continue; }
      FileSystemEntity e = File(path);
      fileList.add(Tuple5(i++, e, "", false, 0));
    }
    update(fileList);
  }

  // 移除文件处理
  delFile(int index) {
    fileList.removeWhere((e) {
      if (e.item1 == index) {
        if (e.item4) {
          infoList.clear();
          thumbFile("");
        }
        return true;
      }
      return false;
    });
    update(fileList);
  }

  // 当文件被点击
  onTapDir(int index) {
    print("$index select");
    for ( var i=0; i<fileList.length; i++) {
      var e = fileList[i];
      if (e.item4 == false && e.item1 == index) {
        fileList[i] = Tuple5(e.item1, e.item2, e.item3, true, e.item5);
        infoList.clear();
        printExifOf(e.item2);
        thumbFile(e.item2.path);
        // update(infoList);
      } else if (e.item4 == true) {
        fileList[i] = Tuple5(e.item1, e.item2, e.item3, false, e.item5);
      }
    }

    update(fileList);
  }

  // 产生新文件名
  refreshNewName() async {
    Map<String, int> nameMap = {};

    for ( var i=0; i<fileList.length; i++) {
      final e = fileList[i];
      final path = e.item2.path;
      final time = await _getExifTime(e.item2);
      var newPath = "";

      if (time == bypass) {
        newPath = bypass;
      } else {
        var newName = "$time.jpg";
        int? v = nameMap[time];
        if (v == null) {
          nameMap[time] = 0;
        } else {
          v += 1;
          nameMap[time] = v;
          newName = sprintf("%s(%04i).jpg", [time, v]);
        }

        var _dir = saveMode2Dir??p.dirname(path);
        newPath = p.join(_dir, newName);
      }

      fileList[i] = Tuple5(e.item1, e.item2, newPath, e.item4, 0);
    }

    update(fileList);
  }

  // 获取文件的Exif信息
  Future<String> _getExifTime(FileSystemEntity e) async {
    String newName = "";
    try {
      Map<String, IfdTag> data = await readExifFromBytes(
          (e as File).readAsBytesSync());
      var tag = data['Image DateTime'].toString();
      var dt = DateFormat('yyyy:MM:dd HH:mm:ss').parse(tag).toLocal();
      var format = FileNameStyleMap.firstWhere((e) => e.item1 == fileNameStyleSelected.value).item2;
      newName = DateFormat(format).format(dt).toString();
      print("$tag => $newName");
    } catch(err) {
      print("get exif time err: ${e.path}, $err");
    }

    //  如果没获取到Exif内的时间且选择忽略
    if (newName == "" && notExifSelected.compareTo("1") == 0) {
      return bypass;
    }

    // 如果没获取到Exif内的时间且选择忽略
    // (newName == "" && notExifSelected.compareTo("2") == 0)
    try {
      var dt = (e as File).statSync().modified;
      var format = FileNameStyleMap.firstWhere((e) => e.item1 == fileNameStyleSelected.value).item2;
      newName = DateFormat(format).format(dt).toString();
      print("modify => $newName");
    } catch(err) {
      print("get modify time err: ${e.path}, $err");
    }

    // 增加前缀
    return "$prefix$newName";
  }

  bool refreshNewNameEnable() {
    return fileList.isNotEmpty;
  }

  bool runEnable() {
    if (fileList.isEmpty) { return false; }

    var e = fileList.elementAt(0);
    if (e.item3 == "") {
      return false;
    }

    return true;
  }

  start() {
    for ( var i=0; i<fileList.length; i++) {
      final e = fileList[i];
      final entity = e.item2;
      final newPath = e.item3;
      if (newPath == bypass) { continue; }
      var res = 0;
      try {
        if (saveModeSelected.compareTo("1") == 0) { // 替换源文件
          (entity as File).renameSync(newPath);
        } else if (saveModeSelected.compareTo("2") == 0) { // 复制创建新文件
          (entity as File).copySync(newPath);
        }
        res = 1; // ok
      } catch(err) {
        print("rename $err");
        res = 2;
      }
      fileList[i] = Tuple5(e.item1, e.item2, e.item3, e.item4, res);
    }
    update(fileList);
  }
}

